"""
监控系统配置
定义性能监控、指标收集、告警规则和通知渠道的配置
"""
from typing import Dict, List, Optional
from pydantic import BaseModel, Field
import os
from utils.logger import global_logger


class AlertRuleConfig(BaseModel):
    """告警规则配置"""
    name: str = Field(..., description="规则名称")
    metric_name: str = Field(..., description="指标名称")
    condition: str = Field(..., description="条件: >, <, ==, !=, >=, <=")
    threshold: float = Field(..., description="阈值")
    duration: int = Field(default=300, description="持续时间（秒）")
    level: str = Field(default="warning", description="告警级别: info, warning, critical, emergency")
    description: str = Field(default="", description="告警描述")
    enabled: bool = Field(default=True, description="是否启用")
    cooldown: int = Field(default=300, description="告警冷却时间（秒）")


class NotificationChannelConfig(BaseModel):
    """通知渠道配置"""
    type: str = Field(..., description="渠道类型: webhook, email, sms, slack")
    enabled: bool = Field(default=True, description="是否启用")
    config: Dict[str, any] = Field(default_factory=dict, description="渠道配置")


class MetricsCollectorConfig(BaseModel):
    """指标收集器配置"""
    enabled: bool = Field(default=True, description="是否启用")
    collect_interval: int = Field(default=30, description="收集间隔（秒）")
    retention_hours: int = Field(default=24, description="数据保留时间（小时）")
    system_metrics: bool = Field(default=True, description="是否收集系统指标")
    custom_metrics: bool = Field(default=True, description="是否收集自定义指标")


class AlertManagerConfig(BaseModel):
    """告警管理器配置"""
    enabled: bool = Field(default=True, description="是否启用")
    check_interval: int = Field(default=60, description="检查间隔（秒）")
    max_events: int = Field(default=1000, description="最大告警事件数量")
    default_rules: List[AlertRuleConfig] = Field(default_factory=list, description="默认告警规则")
    channels: List[NotificationChannelConfig] = Field(default_factory=list, description="通知渠道")


class DashboardConfig(BaseModel):
    """监控Dashboard配置"""
    enabled: bool = Field(default=True, description="是否启用")
    host: str = Field(default="0.0.0.0", description="主机地址")
    port: int = Field(default=8080, description="端口")
    refresh_interval: int = Field(default=30, description="刷新间隔（秒）")


class ModelMonitorConfig(BaseModel):
    """模型监控配置"""
    enabled: bool = Field(default=True, description="是否启用")
    inference_latency_threshold: float = Field(default=5.0, description="推理延迟阈值（秒）")
    memory_usage_threshold: float = Field(default=85.0, description="内存使用率阈值（%）")
    gpu_usage_threshold: float = Field(default=90.0, description="GPU使用率阈值（%）")
    error_rate_threshold: float = Field(default=5.0, description="错误率阈值（%）")


class ResourceMonitorConfig(BaseModel):
    """资源监控配置"""
    enabled: bool = Field(default=True, description="是否启用")
    check_interval: int = Field(default=5, description="检查间隔（秒）")
    cpu_threshold_high: float = Field(default=85.0, description="CPU使用率高阈值（%）")
    cpu_threshold_critical: float = Field(default=95.0, description="CPU使用率严重阈值（%）")
    memory_threshold_high: float = Field(default=85.0, description="内存使用率高阈值（%）")
    memory_threshold_critical: float = Field(default=95.0, description="内存使用率严重阈值（%）")
    disk_threshold_high: float = Field(default=85.0, description="磁盘使用率高阈值（%）")
    disk_threshold_critical: float = Field(default=95.0, description="磁盘使用率严重阈值（%）")


class PerformanceMonitorConfig(BaseModel):
    """性能监控配置"""
    enabled: bool = Field(default=True, description="是否启用")
    metrics: MetricsCollectorConfig = Field(default_factory=MetricsCollectorConfig, description="指标收集器配置")
    alerts: AlertManagerConfig = Field(default_factory=AlertManagerConfig, description="告警管理器配置")
    dashboard: DashboardConfig = Field(default_factory=DashboardConfig, description="Dashboard配置")
    model_monitor: ModelMonitorConfig = Field(default_factory=ModelMonitorConfig, description="模型监控配置")
    resource_monitor: ResourceMonitorConfig = Field(default_factory=ResourceMonitorConfig, description="资源监控配置")


# 预定义配置模板
MONITORING_CONFIG_TEMPLATES = {
    "development": PerformanceMonitorConfig(
        enabled=True,
        metrics=MetricsCollectorConfig(
            collect_interval=30,
            retention_hours=24,
        ),
        alerts=AlertManagerConfig(
            check_interval=60,
            default_rules=[
                AlertRuleConfig(
                    name="high_cpu_usage",
                    metric_name="system.cpu.usage",
                    condition=">",
                    threshold=80.0,
                    duration=300,
                    level="warning",
                    description="CPU使用率过高"
                ),
                AlertRuleConfig(
                    name="high_memory_usage",
                    metric_name="system.memory.usage",
                    condition=">",
                    threshold=85.0,
                    duration=300,
                    level="warning",
                    description="内存使用率过高"
                ),
            ],
            channels=[
                NotificationChannelConfig(
                    type="webhook",
                    enabled=False,
                    config={
                        "url": os.getenv("MONITORING_WEBHOOK_URL", "")
                    }
                )
            ]
        ),
        dashboard=DashboardConfig(
            enabled=True,
            port=8080
        )
    ),
    "production": PerformanceMonitorConfig(
        enabled=True,
        metrics=MetricsCollectorConfig(
            collect_interval=15,
            retention_hours=72,
        ),
        alerts=AlertManagerConfig(
            check_interval=30,
            default_rules=[
                AlertRuleConfig(
                    name="high_cpu_usage",
                    metric_name="system.cpu.usage",
                    condition=">",
                    threshold=75.0,
                    duration=300,
                    level="warning",
                    description="CPU使用率过高"
                ),
                AlertRuleConfig(
                    name="critical_cpu_usage",
                    metric_name="system.cpu.usage",
                    condition=">",
                    threshold=90.0,
                    duration=180,
                    level="critical",
                    description="CPU使用率严重过高"
                ),
                AlertRuleConfig(
                    name="high_memory_usage",
                    metric_name="system.memory.usage",
                    condition=">",
                    threshold=80.0,
                    duration=300,
                    level="warning",
                    description="内存使用率过高"
                ),
                AlertRuleConfig(
                    name="critical_memory_usage",
                    metric_name="system.memory.usage",
                    condition=">",
                    threshold=90.0,
                    duration=180,
                    level="critical",
                    description="内存使用率严重过高"
                ),
                AlertRuleConfig(
                    name="high_disk_usage",
                    metric_name="system.disk.usage",
                    condition=">",
                    threshold=85.0,
                    duration=600,
                    level="warning",
                    description="磁盘使用率过高"
                ),
                AlertRuleConfig(
                    name="high_error_rate",
                    metric_name="app.errors.rate",
                    condition=">",
                    threshold=5.0,
                    duration=300,
                    level="warning",
                    description="错误率过高"
                ),
                AlertRuleConfig(
                    name="high_response_time",
                    metric_name="app.response_time.avg",
                    condition=">",
                    threshold=3000.0,
                    duration=300,
                    level="warning",
                    description="响应时间过长"
                ),
                AlertRuleConfig(
                    name="low_cache_hit_rate",
                    metric_name="app.cache.hit_rate",
                    condition="<",
                    threshold=60.0,
                    duration=600,
                    level="info",
                    description="缓存命中率过低"
                ),
                AlertRuleConfig(
                    name="model_inference_latency",
                    metric_name="model.inference.latency",
                    condition=">",
                    threshold=5000.0,
                    duration=300,
                    level="warning",
                    description="模型推理延迟过高"
                ),
                AlertRuleConfig(
                    name="model_error_rate",
                    metric_name="model.errors.rate",
                    condition=">",
                    threshold=3.0,
                    duration=300,
                    level="warning",
                    description="模型错误率过高"
                )
            ],
            channels=[
                NotificationChannelConfig(
                    type="webhook",
                    enabled=True,
                    config={
                        "url": os.getenv("MONITORING_WEBHOOK_URL", ""),
                        "timeout": 10
                    }
                ),
                NotificationChannelConfig(
                    type="email",
                    enabled=True,
                    config={
                        "smtp_server": os.getenv("SMTP_SERVER", "smtp.example.com"),
                        "smtp_port": int(os.getenv("SMTP_PORT", "587")),
                        "smtp_user": os.getenv("SMTP_USER", ""),
                        "smtp_password": os.getenv("SMTP_PASSWORD", ""),
                        "from_email": os.getenv("ALERT_FROM_EMAIL", "alerts@example.com"),
                        "to_emails": os.getenv("ALERT_TO_EMAILS", "").split(",")
                    }
                )
            ]
        ),
        dashboard=DashboardConfig(
            enabled=True,
            port=8080,
            refresh_interval=15
        ),
        model_monitor=ModelMonitorConfig(
            enabled=True,
            inference_latency_threshold=3.0,
            memory_usage_threshold=80.0
        ),
        resource_monitor=ResourceMonitorConfig(
            enabled=True,
            check_interval=3,
            cpu_threshold_high=75.0,
            cpu_threshold_critical=90.0
        )
    )
}


def get_monitoring_config(env: str = "development") -> PerformanceMonitorConfig:
    """
    获取监控配置
    
    Args:
        env: 环境名称 (development, testing, production)
    
    Returns:
        性能监控配置对象
    """
    try:
        if env in MONITORING_CONFIG_TEMPLATES:
            config = MONITORING_CONFIG_TEMPLATES[env]
            global_logger.info(f"加载监控配置: {env}")
            return config
        else:
            global_logger.warning(f"未知环境: {env}，使用默认配置")
            return MONITORING_CONFIG_TEMPLATES["development"]
    except Exception as e:
        global_logger.error(f"加载监控配置失败: {e}")
        return MONITORING_CONFIG_TEMPLATES["development"]


def validate_monitoring_config(config: PerformanceMonitorConfig) -> bool:
    """
    验证监控配置
    
    Args:
        config: 监控配置对象
    
    Returns:
        是否有效
    """
    try:
        # 基础验证
        if config.metrics.collect_interval <= 0:
            global_logger.error("指标收集间隔必须大于0")
            return False
        
        if config.metrics.retention_hours <= 0:
            global_logger.error("数据保留时间必须大于0")
            return False
        
        if config.alerts.check_interval <= 0:
            global_logger.error("告警检查间隔必须大于0")
            return False
        
        if config.dashboard.port <= 0 or config.dashboard.port > 65535:
            global_logger.error(f"Dashboard端口无效: {config.dashboard.port}")
            return False
        
        # 验证告警规则
        for rule in config.alerts.default_rules:
            if rule.condition not in [">", "<", "==", "!=", ">=", "<="]:
                global_logger.error(f"无效的告警条件: {rule.condition} (规则: {rule.name})")
                return False
            
            if rule.duration <= 0:
                global_logger.error(f"告警持续时间必须大于0 (规则: {rule.name})")
                return False
            
            if rule.level not in ["info", "warning", "critical", "emergency"]:
                global_logger.error(f"无效的告警级别: {rule.level} (规则: {rule.name})")
                return False
        
        global_logger.info("监控配置验证通过")
        return True
        
    except Exception as e:
        global_logger.error(f"验证监控配置失败: {e}")
        return False